import { GameData, GameInitInfo, PlayerInitInfo } from "../GameInterferce";
import GOBERTS, { ActionArgs, PlayerInfo } from "../GOBERTS";
import config from "./Config";
import Context from "./Context";

export class Game {
    private gameInitInfo: GameInitInfo;
    private logger: {
        info: Function,
        warn: Function,
        error: Function
    };
    private frameRate: number;
    private roomId: string;
    private frameClock: NodeJS.Timeout | null = null;

    private index: number = 0;
    private gameContext: Context | null = null;

    private coinSlickMap: Map<number, string[]> = new Map();
    constructor(gameInitInfo: GameInitInfo, logger: any, frameRate: number, roomId: string) {
        this.gameInitInfo = gameInitInfo;
        this.logger = logger;
        this.frameRate = frameRate;
        this.roomId = roomId;

    }

    /**
     * 初始化玩家
     * @param playerInfo 玩家信息
     */
    initPlayer(playerInfo: PlayerInfo) {
        for (let i = 0; i < this.gameInitInfo.playerArr.length; i++) {
            if (this.gameInitInfo.playerArr[i].playerId === playerInfo.playerId) {
                return;
            }
        }
        let data: PlayerInitInfo = {
            playerId: playerInfo.playerId,
            seatIndex: this.gameInitInfo.playerArr.length,
            coin: 0,
            waitCoin: 0
        }
        this.gameInitInfo.playerArr.push(data);
    }

    joinPlaer(playerInfo: PlayerInfo) {
        for (let i = 0; i < this.gameInitInfo.playerArr.length; i++) {
            if (this.gameInitInfo.playerArr[i].playerId === playerInfo.playerId) {
                return;
            }
        }
        let data: PlayerInitInfo = {
            playerId: playerInfo.playerId,
            seatIndex: this.gameInitInfo.playerArr.length,
            coin: 0,
            waitCoin: 0
        }
        this.gameInitInfo.playerArr.push(data);
        this.sendRoomData();
    }

    leavePlayer(playerInfo: PlayerInfo) {
        for (let i = 0; i < this.gameInitInfo.playerArr.length; i++) {
            if (this.gameInitInfo.playerArr[i].playerId === playerInfo.playerId) {
                this.gameInitInfo.playerArr.splice(i, 1);
                break;
            }
        }
        this.sendRoomData();

    }

    getPlayers() {
        return this.gameInitInfo.playerArr;
    }


    startGame(args: ActionArgs) {
        this.startFrameClock(args);
        this.sendRoomData();
        return;
        if (this.gameInitInfo.playerArr.length === 4) {
            this.startFrameClock(args);
            this.sendRoomData();
            return
        }
        this.SendData(args, JSON.stringify({ type: 'Toast', data: "人数不足4人，当前人数：" + this.gameInitInfo.playerArr.length }));
    }

    setPlayerSlick(playerId: string, slickIndx: number, args: GOBERTS.ActionArgs) {
        try {
            let player = this.gameInitInfo.playerArr.find(player => player.playerId === playerId);
            if (player === undefined) {
                this.SendData(args, JSON.stringify({ type: 'Toast', data: "玩家已不再房间" + args.roomId }));
                return;
            }
            if (player.isSlick) {
                this.SendData(args, JSON.stringify({ type: 'Toast', data: "玩家已经选择无法更改" }, [playerId]));
                return;
            }

            player.isSlick = true;

            let playerArr = this.coinSlickMap.get(slickIndx);
            if (playerArr) {
                this.coinSlickMap.set(slickIndx, playerArr.concat(playerId));
            } else {
                this.coinSlickMap.set(slickIndx, [playerId]);
            }

            this.sendRoomData();
        } catch (error) {
        }

    }
    getSlickResults() {
        return Object.fromEntries(this.coinSlickMap);
    }
    resertSlickData() {
        // 遍历 coinSlickMap
        this.coinSlickMap.forEach((playerIds, coinIndex) => {
            if (playerIds.length == 1) {
                const player = this.gameInitInfo.playerArr.find(p => p.playerId === playerIds[0]);
                if (player) {
                    // 给玩家的 coin 属性增加奖励数量
                    player.coin += config.coins[this.gameContext?.stepIndex ? this.gameContext?.stepIndex : 0][coinIndex];
                }
            }
            this.gameInitInfo.playerArr.forEach(player => {
                player.isSlick = false;
            })
        });

        this.coinSlickMap = new Map();
    }

    /**
     * 启动帧时钟
     * @param args 动作参数
     */
    public startFrameClock(args: GOBERTS.ActionArgs) {
        if (this.gameContext !== null) {
            return;
        }
        this.gameContext = new Context(args, this);
        this.SendData(args, JSON.stringify({ type: 'Toast', data: "startFrameClock" + args.roomId }));

        this.gameContext.request();

        // args.SDK.log.info('startFrameClock' + this.roomId);
        // if (this.frameClock !== null) return;
        // this.frameClock = setInterval(() => {
        //     this.index++;
        //     let gameData: GameData = { type: 'InitGame', data: "success,回合:" + this.index };
        //     args.SDK.sendData(JSON.stringify(gameData)).then().catch(err => {
        //         args.SDK.log.error('send Collide fail, roomId:' + this.roomId + 'err:' + err);
        //     });
        // }, 10000);
    }

    public stopFrameClock(args: GOBERTS.ActionArgs) {
        args.SDK.log.info('stopFrameClock' + this.roomId);
        clearInterval(this.frameClock!);
        this.frameClock = null;
    }
    public SendData(args: GOBERTS.ActionArgs, data: string, players?: string[]) {
        // 广播游戏进度
        args.SDK.sendData(data, players).then().catch(err => {
            args.SDK.log.error('Toast' + err);
        });
    }



    //////////////////////发送客户端//////////
    sendRoomData() {
        let gameData: GameData = { type: 'RoomInfo', data: JSON.stringify(this.gameInitInfo) };
        this.gameContext?.sendData(JSON.stringify(gameData));
    }

    sendPKData() {
        this.gameInitInfo.type = "Pk";
        this.gameInitInfo.coinData = config.coins[this.gameContext?.stepIndex ? this.gameContext?.stepIndex : 0];
        this.gameInitInfo.endTime = Date.now() + 10000;
        this.gameInitInfo.pkResult = this.getSlickResults();

        let gameData: GameData = { type: 'Pk', data: JSON.stringify(this.gameInitInfo) };
        this.gameContext?.sendData(JSON.stringify(gameData));
    }

    sendPKResult() {

        this.gameInitInfo.type = "PKResult";
        this.gameInitInfo.coinData = config.coins[this.gameContext?.stepIndex ? this.gameContext?.stepIndex : 0];
        this.gameInitInfo.stepIndex = this.gameContext?.stepIndex ? this.gameContext?.stepIndex : 0;
        this.gameInitInfo.endTime = Date.now() + 10000;
        this.gameInitInfo.pkResult = this.getSlickResults();
        let gameData: GameData = { type: 'PKResult', data: JSON.stringify(this.gameInitInfo) };
        this.gameContext?.sendData(JSON.stringify(gameData));
    }


}